//! HTTP事件数据结构定义

use chrono::{DateTime, Utc};
use http::{Method, StatusCode, Uri};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
// use uuid::Uuid;

/// HTTP事件类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum EventType {
    /// HTTP请求
    Request,
    /// HTTP响应
    Response,
}

/// HTTP事件元数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EventMetadata {
    /// 事件唯一ID
    pub id: String,
    /// 事件时间戳
    pub timestamp: DateTime<Utc>,
    /// 事件类型
    pub event_type: EventType,
    /// 来源IP
    pub source_ip: String,
    /// 目标主机
    pub host: String,
    /// 连接ID (用于关联请求和响应)
    pub connection_id: String,
    /// 处理耗时 (微秒)
    pub duration_us: Option<u64>,
}

impl EventMetadata {
    /// 创建新的事件元数据
    pub fn new(
        event_type: EventType,
        source_ip: String,
        host: String,
        connection_id: String,
    ) -> Self {
        Self {
            id: uuid::Uuid::new_v4().to_string(),
            timestamp: Utc::now(),
            event_type,
            source_ip,
            host,
            connection_id,
            duration_us: None,
        }
    }

    /// 设置处理耗时
    pub fn with_duration(mut self, duration_us: u64) -> Self {
        self.duration_us = Some(duration_us);
        self
    }
}

/// HTTP事件主体数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HttpEvent {
    /// 事件元数据
    pub metadata: EventMetadata,
    /// HTTP方法 (仅请求)
    pub method: Option<String>,
    /// 请求URI (仅请求)
    pub uri: Option<String>,
    /// HTTP状态码 (仅响应)
    pub status_code: Option<String>,
    /// HTTP头部
    pub headers: HashMap<String, String>,
    /// 请求体/响应体摘要 (SHA256)
    pub body_hash: Option<String>,
    /// 请求体/响应体大小
    pub body_size: usize,
    /// 内容类型
    pub content_type: Option<String>,
    /// 用户代理
    pub user_agent: Option<String>,
    /// 请求参数 (仅请求)
    pub query_params: Option<HashMap<String, String>>,
    /// 路径信息
    pub path: Option<String>,
    /// 协议版本
    pub version: Option<String>,
}

impl HttpEvent {
    /// 创建HTTP请求事件
    pub fn new_request(
        method: Method,
        uri: Uri,
        headers: HashMap<String, String>,
        body: &[u8],
        source_ip: String,
        connection_id: String,
    ) -> Self {
        let uri_str = uri.to_string();
        let path = uri.path().to_string();
        let query_params = Self::extract_query_params_str(&uri_str);
        
        let mut event = Self {
            metadata: EventMetadata::new(
                EventType::Request,
                source_ip,
                uri.host().unwrap_or("unknown").to_string(),
                connection_id,
            ),
            method: Some(method.to_string()),
            uri: Some(uri_str),
            status_code: None,
            headers,
            body_hash: Some(Self::hash_body(body)),
            body_size: body.len(),
            content_type: None,
            user_agent: None,
            query_params,
            path: Some(path),
            version: None,
        };

        // 提取常用头部信息
        if let Some(content_type) = event.headers.get("content-type") {
            event.content_type = Some(content_type.clone());
        }
        if let Some(user_agent) = event.headers.get("user-agent") {
            event.user_agent = Some(user_agent.clone());
        }

        event
    }

    /// 创建HTTP响应事件
    pub fn new_response(
        status_code: StatusCode,
        headers: HashMap<String, String>,
        body: &[u8],
        connection_id: String,
    ) -> Self {
        let host = headers
            .get("host")
            .cloned()
            .unwrap_or_else(|| "unknown".to_string());

        let mut event = Self {
            metadata: EventMetadata::new(
                EventType::Response,
                "server".to_string(),
                host,
                connection_id,
            ),
            method: None,
            uri: None,
            status_code: Some(status_code.to_string()),
            headers,
            body_hash: Some(Self::hash_body(body)),
            body_size: body.len(),
            content_type: None,
            user_agent: None,
            query_params: None,
            path: None,
            version: None,
        };

        // 提取常用头部信息
        if let Some(content_type) = event.headers.get("content-type") {
            event.content_type = Some(content_type.clone());
        }
        if let Some(server) = event.headers.get("server") {
            event.version = Some(server.clone());
        }

        event
    }

    /// 计算请求体/响应体哈希
    fn hash_body(body: &[u8]) -> String {
        use sha2::{Digest, Sha256};
        let mut hasher = Sha256::new();
        hasher.update(body);
        format!("{:x}", hasher.finalize())
    }

    /// 从URI字符串中提取查询参数
    fn extract_query_params_str(uri_str: &str) -> Option<HashMap<String, String>> {
        if let Some(query_start) = uri_str.find('?') {
            let query = &uri_str[query_start + 1..];
            if !query.is_empty() {
                let mut params = HashMap::new();
                for pair in query.split('&') {
                    if let Some((key, value)) = pair.split_once('=') {
                        params.insert(
                            urlencoding::decode(key).unwrap_or_default().to_string(),
                            urlencoding::decode(value).unwrap_or_default().to_string(),
                        );
                    }
                }
                Some(params)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// 获取事件的唯一标识符 (用于去重)
    pub fn get_unique_key(&self) -> String {
        match &self.metadata.event_type {
            EventType::Request => {
                format!(
                    "{}:{}:{}:{}",
                    self.metadata.host,
                    self.path.as_deref().unwrap_or("/"),
                    self.method.as_deref().unwrap_or("GET"),
                    self.body_hash.as_deref().unwrap_or("")
                )
            }
            EventType::Response => {
                format!(
                    "{}:{}:{}:{}",
                    self.metadata.host,
                    self.path.as_deref().unwrap_or("/"),
                    self.status_code.as_ref().and_then(|s| s.parse::<u16>().ok()).unwrap_or(200),
                    self.body_hash.as_deref().unwrap_or("")
                )
            }
        }
    }

    /// 获取基础路径 (用于指纹识别)
    pub fn get_base_path(&self) -> String {
        self.path
            .as_ref()
            .map(|p| {
                // 移除查询参数和锚点
                if let Some(end) = p.find(['?', '#']) {
                    p[..end].to_string()
                } else {
                    p.clone()
                }
            })
            .unwrap_or_else(|| "/".to_string())
    }

    /// 判断是否为静态资源
    pub fn is_static_resource(&self) -> bool {
        if let Some(path) = &self.path {
            let static_extensions = [
                ".css", ".js", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg", ".woff", ".woff2",
                ".ttf", ".eot", ".pdf", ".zip", ".rar", ".tar", ".gz",
            ];
            static_extensions.iter().any(|ext| path.to_lowercase().ends_with(ext))
        } else {
            false
        }
    }

    /// 判断是否为API请求
    pub fn is_api_request(&self) -> bool {
        if let Some(path) = &self.path {
            path.starts_with("/api/") || path.contains("/v1/") || path.contains("/v2/")
        } else {
            false
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use http::Uri;

    #[test]
    fn test_http_event_creation() {
        let mut headers = HashMap::new();
        headers.insert("content-type".to_string(), "application/json".to_string());
        headers.insert("user-agent".to_string(), "test-agent".to_string());

        let uri = "https://example.com/api/test?param=value".parse::<Uri>().unwrap();
        let event = HttpEvent::new_request(
            http::Method::GET,
            uri,
            headers,
            b"test body",
            "127.0.0.1".to_string(),
            "conn-123".to_string(),
        );

        assert_eq!(event.method, Some("GET".to_string()));
        assert_eq!(event.content_type, Some("application/json".to_string()));
        assert_eq!(event.user_agent, Some("test-agent".to_string()));
        assert_eq!(event.path, Some("/api/test".to_string()));
        assert!(event.is_api_request());
        assert!(!event.is_static_resource());
    }
}